package com.rightsidetech.http.wechatutil;

import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransOrderQueryModel;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.internal.util.StringUtils;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.rightsidetech.commom.dto.response.TransferModelResp;
import com.rightsidetech.commom.utils.HttpClient;
import com.rightsidetech.http.config.WechatConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;

import java.math.BigDecimal;
import java.util.Map;

@Slf4j
public class TransferUtils {

    /**
     * 支付宝原路退回
     * @param orderNo 商户订单号
     * @param otherOrderNo 第三方订单号
     * @param accountId 用户id
     * @param amount 金额
     * @param refundReason 退款描述
     * @return
     * @throws Exception
     */
    public static TransferModelResp alipayOriginalRefund(DefaultAlipayClient alipayClient, String orderNo, String otherOrderNo, String accountId, BigDecimal amount, String refundReason) throws Exception{
        try {
            AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
            AlipayTradeRefundModel alipayTradeRefundModel = new AlipayTradeRefundModel();
            alipayTradeRefundModel.setTradeNo(otherOrderNo);
            alipayTradeRefundModel.setRefundAmount(String.valueOf(amount));
            alipayTradeRefundModel.setRefundReason(refundReason);
            alipayTradeRefundModel.setOutRequestNo(accountId);
            alipayTradeRefundModel.setOperatorId(accountId);
            refundRequest.setBizModel(alipayTradeRefundModel);
            AlipayTradeRefundResponse response = alipayClient.certificateExecute(refundRequest);
            if (response.isSuccess()) {
                String code = response.getCode();
                if("Y".equals(response.getFundChange()) && "10000".equals(code)){
                    log.info("支付宝支付:商户订单号"+ orderNo +",退款成功");
                    return new TransferModelResp(true, null, response.getBody());
                }
                log.info("支付宝支付:商户订单号"+ orderNo +",退款失败");
            } else {
                log.info("支付宝支付:商户订单号"+ orderNo +",退款失败,网关返回码:" + response.getCode() + ",网关返回码描述:" + response.getMsg());
            }
            return new TransferModelResp(response.getSubCode(), response.getSubMsg(), response.getBody());
        }catch (Exception e){
            log.error("支付宝支付:支付宝退款接口调用出错", e);
            return new TransferModelResp();
        }
    }

    /**
     * 支付宝转账
     * @param transOrderNo 转账商户订单号
     * @param amount 金额
     * @param map 支付返回参数
     * @param identity 支付宝唯一标识
     * @param realName 真实姓名
     * @param orderTitle 转账标题
     * @return
     * @throws Exception
     */
    public static TransferModelResp aliPayFundTransToAccount(DefaultAlipayClient alipayClient, String transOrderNo, BigDecimal amount, Map map, String identity, String realName, String orderTitle) throws Exception{
        try {
            AlipayFundTransUniTransferRequest alipayFundTransUniTransferRequest = new AlipayFundTransUniTransferRequest();
            AlipayFundTransUniTransferModel alipayFundTransUniTransferModel = new AlipayFundTransUniTransferModel();
            alipayFundTransUniTransferModel.setOutBizNo(transOrderNo);
            alipayFundTransUniTransferModel.setBizScene("DIRECT_TRANSFER");
            alipayFundTransUniTransferModel.setTransAmount(String.valueOf(amount));
            alipayFundTransUniTransferModel.setProductCode("TRANS_ACCOUNT_NO_PWD");
            alipayFundTransUniTransferModel.setOrderTitle(orderTitle);
            //收款方信息
            Participant payeeInfo = new Participant();
            if(MapUtils.isEmpty(map)){
                // 1、ALIPAY_LOGON_ID：支付宝登录号，支持邮箱和手机号格式。
                payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
                payeeInfo.setIdentity(identity);
                payeeInfo.setName(realName);
            }else {
                // 2、ALIPAY_USERID：支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。
                payeeInfo.setIdentityType("ALIPAY_USER_ID");
                payeeInfo.setIdentity(String.valueOf(map.get("buyer_id")));
            }
            alipayFundTransUniTransferModel.setPayeeInfo(payeeInfo);
            //付款方信息
            Participant payerInfo = new Participant();
            payeeInfo.setMerchantUserInfo("merchant_user_name");
            alipayFundTransUniTransferModel.setPayerInfo(payerInfo);
            alipayFundTransUniTransferRequest.setBizModel(alipayFundTransUniTransferModel);

            AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(alipayFundTransUniTransferRequest);
            String subMsg = response.getSubMsg();
            String subCode = response.getSubCode();
            if (response.isSuccess()) {
                if("SUCCESS".equals(response.getStatus()) && "10000".equals(response.getCode())){
                    log.info("支付宝支付:商户订单号"+ transOrderNo +",转账成功");
                    return new TransferModelResp(true, response.getOrderId(), response.getBody());
                }
                if("SYSTEM_ERROR".equals(subCode)){
                    log.info("支付宝支付:商户订单号"+ transOrderNo +",转账失败,系统繁忙,查询订单状态");
                    AlipayFundTransOrderQueryRequest alipayFundTransOrderQueryRequest = new AlipayFundTransOrderQueryRequest();
                    AlipayFundTransOrderQueryModel alipayFundTransOrderQueryModel = new AlipayFundTransOrderQueryModel();
                    alipayFundTransOrderQueryModel.setOutBizNo(transOrderNo);
                    alipayFundTransOrderQueryRequest.setBizModel(alipayFundTransOrderQueryModel);
                    AlipayFundTransOrderQueryResponse transOrderQueryResponse = alipayClient.certificateExecute(alipayFundTransOrderQueryRequest);
                    if(transOrderQueryResponse.isSuccess()){
                        if("10000".equals(transOrderQueryResponse.getCode())){
                            log.info("支付宝支付:商户订单号"+ transOrderNo +"状态:" + transOrderQueryResponse.getStatus());
                            if("SUCCESS".equals(transOrderQueryResponse.getStatus())){
                                return new TransferModelResp(true, response.getOrderId(), response.getBody());
                            }
                        }
                        log.info("支付宝支付:商户订单号"+ transOrderNo +"查询失败,网关返回码:" + transOrderQueryResponse.getCode()+ ",网关返回码描述:" + transOrderQueryResponse.getMsg());
                    }else{
                        log.info("支付宝支付:查询商户订单号"+ transOrderNo +"失败,网关返回码:" + transOrderQueryResponse.getCode() + ",网关返回码描述:" + transOrderQueryResponse.getMsg());
                    }
                }
                log.info("支付宝支付:商户订单号"+ transOrderNo +"转账失败,原因:" + subMsg);
            } else {
                log.info("支付宝支付:商户订单号"+ transOrderNo +",转账失败,网关返回码:" + response.getCode() + ",网关返回码描述:" + response.getMsg());
            }
            return new TransferModelResp(subCode, subMsg, response.getBody());
        }catch (Exception e){
            log.error("支付宝支付:支付宝转账接口调用出错", e);
            return new TransferModelResp();
        }
    }


    /* *
     *微信原路退回
     * @param orderNo 订单号
     * @param amount 金额
     * @param returnMap 支付返回参数
     * @return
     * @throws Exception
     * */
    public static TransferModelResp weichatOriginalRefund(WechatConfig wechatConfig, String orderNo, BigDecimal amount, Map returnMap) throws Exception{
        try {
            HttpClient httpClient = new HttpClient(WechatConfig.REFUND_URL, 3000, 3000);
            String xml = WechatUtil.genRefundReq(wechatConfig.getWechatAppId(), wechatConfig.getApiKey(), wechatConfig.getMchId(), String.valueOf(returnMap.get("transaction_id")), orderNo, String.valueOf(returnMap.get("total_fee")), Integer.toString(amount.intValue()), "CYN");
            log.info("微信支付:商户订单号" + orderNo + ",请求参数:" + xml);
            xml = httpClient.sendXmlCert(xml, "UTF-8", wechatConfig.getRefundCertPath(), wechatConfig.getMchId());
            if (!StringUtils.isEmpty(xml)) {
                Map<String, Object> map = WechatUtil.getMapFromXML(xml);
                if (map.get("return_code").equals("SUCCESS")) {
                    if (map.get("result_code").equals("SUCCESS")) {
                        log.info("微信支付:商户订单号" + orderNo + "退款成功");
                        return new TransferModelResp(true, null, xml);
                    } else{
                        if (map.get("err_code").equals("TRADE_OVERDUE")) {
                            log.info("微信支付:商户订单号"+ orderNo +"已经超过退款期限");
                            return new TransferModelResp(true);
                        }
                        String errCodeDes = String.valueOf(map.get("err_code_des"));
                        String errCode = String.valueOf(map.get("err_code"));
                        log.info("微信支付:商户订单号" + orderNo +"退款失败,原因:" + errCodeDes);
                        return new TransferModelResp(errCode, errCodeDes, xml);
                    }
                } else {
                    String returnMsg = String.valueOf(map.get("return_msg"));
                    String returnCode = String.valueOf(map.get("return_code"));
                    log.info("微信支付:商户订单号" + orderNo +"退款失败,原因:" + returnMsg);
                    return new TransferModelResp(returnCode, returnMsg, xml);
                }
            }
            log.info("微信支付:商户订单号" + orderNo +"退款失败,微信返回信息为空");
        } catch (Exception e) {
            log.error("微信支付:微信退款接口调用错误", e);
        }
        return new TransferModelResp();
    }

    /* *
     *微信转账
     * @param transOrderNo 转账商户订单号
     * @param amount 金额
     * @param returnMap 支付返回参数
     * @return
     * @throws Exception
     * */
    public static TransferModelResp weichatTransfers(WechatConfig wechatConfig, String transOrderNo, BigDecimal amount, Map returnMap) throws Exception{
        try{
            HttpClient httpClient = new HttpClient(WechatConfig.TRANSFER_ACCOUNTS, 3000, 3000);
            amount = amount.multiply(BigDecimal.valueOf(100));//转为分
            String xml = WechatUtil.weichatTransfersToUser(transOrderNo, String.valueOf(returnMap.get("openid")), Integer.toString(amount.intValue()), wechatConfig.getCreateIp(), wechatConfig.getWechatAppId(), wechatConfig.getMchId(), wechatConfig.getApiKey());
            xml = httpClient.sendXmlCert(xml, "UTF-8", wechatConfig.getRefundCertPath(), wechatConfig.getMchId());
            if(!StringUtils.isEmpty(xml)){
                Map<String, Object> map = WechatUtil.getMapFromXML(xml);
                if (map.get("return_code").equals("SUCCESS")) {
                    if (map.get("result_code").equals("SUCCESS")) {
                        log.info("微信支付:商户订单号"+ transOrderNo +"转账成功");
                        return new TransferModelResp(true, String.valueOf(map.get("payment_no")), xml);
                    }
                    if (map.get("err_code").equals("SYSTEMERROR")) {
                        log.info("微信支付:商户订单号"+ transOrderNo + "转账失败,系统繁忙,进入查询订单状态逻辑");
                        HttpClient infoClient = new HttpClient(WechatConfig.GET_TRANSFER_INFO, 3000, 3000);
                        String infoXml = WechatUtil.getTransferInfoXml(transOrderNo, wechatConfig.getWechatAppId(), wechatConfig.getMchId(), wechatConfig.getApiKey());
                        infoXml = infoClient.sendxml(infoXml, "UTF-8");
                        if (!StringUtils.isEmpty(infoXml)) {
                            Map<String, Object> infoMap = WechatUtil.getMapFromXML(infoXml);
                            if (infoMap.get("return_code").equals("SUCCESS")) {
                                if (infoMap.get("result_code").equals("SUCCESS")) {
                                    log.info("微信支付:商户订单号"+ transOrderNo + "订单状态:" + infoMap.get("status"));
                                    if (infoMap.get("status").equals("SUCCESS")) {
                                        log.info("微信支付:商户订单号"+ transOrderNo + "转账成功");
                                        return new TransferModelResp(true, String.valueOf(map.get("payment_no")), xml);
                                    }
                                    log.info("微信支付:商户订单号"+ transOrderNo +"转账失败,原因:" + infoMap.get("reason"));
                                    return new TransferModelResp(String.valueOf(map.get("err_code")), String.valueOf(map.get("err_code_des")), xml);
                                }
                                log.info("微信支付:商户订单号"+ transOrderNo +"查询订单状态失败,原因:" + infoMap.get("err_code_des"));
                            }
                            log.info("微信支付:商户订单号"+ transOrderNo +"查询订单状态失败,原因:" + infoMap.get("return_msg"));
                        }
                        log.info("微信支付:商户订单号"+ transOrderNo +"查询订单状态失败,微信返回为空");
                        return new TransferModelResp();
                    }
                    log.info("微信支付:商户订单号"+ transOrderNo +"转账失败,原因:" + map.get("err_code_des"));
                    return new TransferModelResp(String.valueOf(map.get("err_code")), String.valueOf(map.get("err_code_des")), xml);
                }
                String returnMsg = String.valueOf(map.get("return_msg"));
                String returnCode = String.valueOf(map.get("return_code"));
                log.info("微信支付:商户订单号"+ transOrderNo +"转账失败,原因:" + returnMsg);
                return new TransferModelResp(returnCode, returnMsg, xml);
            }
            log.info("微信支付:商户订单号"+ transOrderNo +"转账,微信返回信息为空");
        }catch (Exception e){
            log.error("微信支付:微信转账接口调用错误", e);
        }
        return new TransferModelResp();
    }
}
